/*******************************************************************************
 * Copyright (c) quickfixengine.org  All rights reserved. 
 * 
 * This file is part of the QuickFIX FIX Engine 
 * 
 * This file may be distributed under the terms of the quickfixengine.org 
 * license as defined by quickfixengine.org and appearing in the file 
 * LICENSE included in the packaging of this file. 
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING 
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A 
 * PARTICULAR PURPOSE. 
 * 
 * See http://www.quickfixengine.org/LICENSE for licensing information. 
 * 
 * Contact ask@quickfixengine.org if any conditions of this licensing 
 * are not clear to you.
 ******************************************************************************/

package org.activequant.core.domainmodel.account;

import java.io.Serializable;

import org.activequant.core.domainmodel.InstrumentSpecification;
import org.activequant.core.types.OrderSide;
import org.activequant.core.types.OrderTif;
import org.activequant.core.types.OrderType;
import org.activequant.core.types.TimeStamp;

/**
 * Order to sell/buy contracts. Holds the following associated variables:
 * <ul>
 * <li>id(Long)</li>
 * <li>orderType(OrderType)</li>
 * <li>instrumentSpecification(InstrumentSpecification)</li>
 * <li>orderSide(OrderSide)</li>
 * <li>timeInForce(OrderTif)</li>
 * <li>orderTimeStamp(TimeStamp)</li>
 * <li>executionTargetTimeStamp(TimeStamp)</li>
 * <li>expirationTimeStamp(TimeStamp)</li>
 * <li>quantity(double)</li>
 * <li>limitPrice(double)</li>
 * <li>stopPrice(double)</li>
 * <li>trailingDistance(double)</li>
 * </ul>
 * <br>
 * <b>History:</b><br>
 *  - [11.12.2007] Created (Mike Kroutikov)<br>
 *
 *  @author Mike Kroutikov
 */
public class Order implements Serializable {
	
	private static final long serialVersionUID = 3373020883969575772L;

	public static final int NOT_SET = -1;
	/**
	 * private Long id;
	 */
	private Long id;
	/**
	 * private OrderType orderType = OrderType.MARKET;
	 */
	private OrderType orderType = OrderType.MARKET;
	/**
	 * private InstrumentSpecification instrumentSpecification;
	 */
    private InstrumentSpecification instrumentSpecification;
    /**
     * private OrderSide orderSide = OrderSide.BUY;
     */
    private OrderSide orderSide = OrderSide.BUY;
    /**
     * private TimeStamp orderTimeStamp;
     */
    private TimeStamp orderTimeStamp;
    /**
     * private TimeStamp executionTargetTimeStamp;
     */
    private TimeStamp executionTargetTimeStamp;
    /**
     * private TimeStamp expirationTimeStamp;
     */
    private TimeStamp expirationTimeStamp;
    /**
     * private OrderTif timeInForce = OrderTif.DAY;
     */
    private OrderTif timeInForce = OrderTif.DAY;
    /**
     * private double quantity = NOT_SET;
     */
    private double quantity = NOT_SET;
    /**
     * private double limitPrice = NOT_SET;
     */
	private double limitPrice = NOT_SET;
	/**
	 * private double stopPrice = NOT_SET;
	 */
	private double stopPrice = NOT_SET;
	/**
	 * private double trailingDistance = NOT_SET;
	 */
	private double trailingDistance = NOT_SET;
	
	/**
	 * Creates empty Order (an empty constructor).
	 */
	public Order() { 
		
	}
	/**
	 * constructs an Order using the given orderType(OrderType) to set its associated orderType(OrderType)
	 * @param orderType
	 */
	public Order(OrderType orderType) { 
		this.orderType = orderType;
	}
	
	/**
	 * Duplicates an order.
	 * constructs an duplicate Order of the given order(Order)
	 * @param other model order.
	 */
	public Order(Order other) {
		this.id = other.id;
		this.orderType = other.orderType;
		this.instrumentSpecification = other.instrumentSpecification;
		this.orderSide = other.orderSide;
		this.orderTimeStamp = other.orderTimeStamp;
		this.executionTargetTimeStamp = other.executionTargetTimeStamp;
		this.expirationTimeStamp = other.expirationTimeStamp;
		this.timeInForce = other.timeInForce;
		this.quantity = other.quantity;
		this.limitPrice = other.limitPrice;
		this.stopPrice = other.stopPrice;
		this.trailingDistance = other.trailingDistance;
	}
	/**
	 * returns whether the associated id(Long) is not <code>null</code>
	 * @return
	 */
	public boolean hasId() {
		return id != null;         
	}          
	
	/**
	 * Persistence identity (usually auto-generated by the database).<br/>
	 * returns the associated id(Long)
	 * @return the id
	 */
	public Long getId() {
		return id;
	}

	/**
	 * Sets the persistence identity.<br/>
	 * sets the associated id(Long) with the given id(Long)
	 * @param id the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}
	
	/**
	 * Order type (MARKET/LIMIT/STOP_LIMIT, etc).<br/>
	 * returns the associated orderType(OrderType)
	 * @return type.
	 */
	public OrderType getOrderType() {
		return orderType;
	}
	
	/**
	 * Sets order type.<br/>
	 * sets the associated orderType(OrderType) with the given type(OrderType)
	 * @param type order type.
	 */
	public void setOrderType(OrderType type) {
		orderType = type;
	}
    
	/**
	 * Instrument to buy/sell.<br/>
	 * returns the associated instrumentSpecification(InstrumentSpecification)
	 * @return instrument specification;
	 */
    public InstrumentSpecification getInstrumentSpecification() {
        return instrumentSpecification;
    }
    
    /**
     * Sets which instrument to buy/sell.<br/>
     * sets the associated instrumentSpecification(InstrumentSpecification) with the given instrumentSpecification(InstrumentSpecification)
     * @param instrumentSpecification instrument specification.
     */
    public void setInstrumentSpecification(InstrumentSpecification instrumentSpecification) {
        this.instrumentSpecification = instrumentSpecification;
    }

    /**
     * Order side.<br/>
     * returns the associated orderSide(OrderSide)
     * @return order side.
     */
	public OrderSide getOrderSide() {
		return orderSide;
	}

	/**
	 * Sets order side.<br/>
	 * sets the associated orderSide(OrderSide) with the given side(OrderSide)
	 * @param side order side.
	 */
	public void setOrderSide(OrderSide side) {
		this.orderSide = side;
	}

	/**
	 * Time-in-force for this order.<br/>
	 * returns the associated timeInForce(OrderTif)
	 * @return
	 */
	public OrderTif getTimeInForce() {
		return timeInForce;
	}

	/**
	 * Sets time-in-force for this order.<br/>
	 * sets the associated timeInForce(OrderTif) with the given tif(OrderTif)
	 * @param tif time in force.
	 */
	public void setTimeInForce(OrderTif tif) {
		this.timeInForce = tif;
	}

	/**
	 * Time stamp when the order has been created.<br/>
	 * returns the associated orderTimeStamp(TimeStamp)
	 * @return order time stamp.
	 */
	public TimeStamp getOrderTimeStamp() {
		return orderTimeStamp;
	}

	/**
	 * Sets order creation time stamp.<br/>
	 * sets the associated orderTimeStamp(TimeStamp) with the given orderStamp(TimeStamp)
	 * @param orderDate order time stamp.
	 */
	public void setOrderTimeStamp(TimeStamp orderStamp) {
		this.orderTimeStamp = orderStamp;
	}

    /**
     * Specifies when an order must be executed.
     * This could be relevant when using the paper broker implementation.
     * It also reflects a "good starting at".   
     * <p/>
     * An executionPoint of null expresses that the order is executed as soon as possible (does 
     * not collide with Time In Force, as TIF is used at the broker's/exchange's end).<br/>
     * returns the associated executionTargetTimeStamp(TimeStamp)  
     */
	public TimeStamp getExecutionTargetTimeStamp() {
		return executionTargetTimeStamp;
	}

	/**
	 * Sets execution target time stamp.<br/>
	 * sets the associated executionTargetTimeStamp(TimeStamp) with the given val(TimeStamp)
	 * @param val execution target time stamp.
	 */
	public void setExecutionTargetTimeStamp(TimeStamp val) {
		this.executionTargetTimeStamp = val;
	}
	
	/**
	 * Order expiration time stamp for the orders with the appropriate
	 * <code>timeInForce</code> value.<br/>
	 * returns the associated expirationTimeStamp(TimeStamp)
	 * @return expiration time stamp.
	 */
	public TimeStamp getExpirationTimeStamp() {
		return this.expirationTimeStamp;
	}
	
	/**
	 * Sets the expiration time stamp.<br/>
	 * sets the associated expirationTimeStamp(TimeStamp) with the given val(TimeStamp)
	 * @param val expiration time stamp.
	 */
	public void setExpirationTimeStamp(TimeStamp val) {
		this.expirationTimeStamp = val;
	}

    /**
     * Quantity of instrument to buy/sell.<br/>
     * returns the associated quantity(double)
     * @return quantity.
     */
    public double getQuantity() {
        return quantity;
    }
    
    /**
     * Sets the quantity.<br/>
     * sets the associated quantity(double) with the given quantity(double)
     * @param quantity quantity.
     */
    public void setQuantity(double quantity) {
        this.quantity = quantity;
    }

	/**
	 * Limit price.<br/>
	 * returns the associated limitPrice(double)
	 * @return limit price.
	 */
	public double getLimitPrice() {
		return limitPrice;
	}
	
	/**
	 * Sets limit price.<br/>
	 * sets the associated limitPrice(double) with the given val(double)
	 * @param val limit price.
	 */
	public void setLimitPrice(double val) {
		limitPrice = val;
	}


	/**
	 * Stop price.<br/>
	 * returns the associated stopPrice(double)
	 * @return stop price.
	 */
	public double getStopPrice() {
		return stopPrice;
	}
	
	/**
	 * Sets stop price.<br/>
	 * sets the associated stopPrice(double) with the given val(double)
	 * @param val stop price.
	 */
	public void setStopPrice(double val) {
		stopPrice = val;
	}

	/**
	 * Trailing distance.<br/>
	 * returns the associated trailingDistance(double)
	 * @return trailing distance.
	 */
	public double getTrailingDistance() {
		return trailingDistance;
	}
	
	/**
	 * Sets trailing distance.<br/>
	 * sets the associated trailingDistance(double) with the given val(double)
	 * @param val trailing distance.
	 */
	public void setTrailingDistance(double val) {
		trailingDistance = val;
	}
	/**
	 * returns a String in the form: "Order: type=${orderType}, instrument=${instrumentSpecification}, side=${orderSide}, quantity=${quantity}, orderTimeStamp=${orderTimeStamp}, executionTragetTimeStamp=${executionTargetTimeStamp}
    		, expirationTimeStamp=${expirationTimeStamp}, timeInForce=${timeInForce}, orderTimeStamp=${orderTimeStamp}, stopPrice=${stopPrice}, limitPrice=${limitPrice}, trailingDistance=${trailingDistance}"
	 */
    public String toString() {
    	return "Order: type=" + getOrderType()
    		+ ", instrument=" + getInstrumentSpecification()
    		+ ", side=" + getOrderSide()
    		+ ", quantity=" + getQuantity()
    		+ ", orderTimeStamp=" + getOrderTimeStamp()
    		+ ", executionTragetTimeStamp=" + getExecutionTargetTimeStamp()
    		+ ", expirationTimeStamp=" + getExpirationTimeStamp()
    		+ ", timeInForce=" + getTimeInForce()
    		+ ", orderTimeStamp=" + getOrderTimeStamp()
    		+ ", stopPrice=" + getStopPrice()
    		+ ", limitPrice=" + getLimitPrice()
    		+ ", trailingDistance=" + getTrailingDistance();
    }
}